package org.dding.core.log;

import java.util.logging.Level;
import java.util.logging.Logger;

public final class JDKLogger implements ILogger {

	private static final Level TRACE;
	private static final Level DEBUG;
	private static final Level WARN;
	private static final Level ERROR;
	private static final Level INFO;

	static {
		Level trace;
		Level debug;
		Level warn;
		Level error;
		Level info;
		try {
			trace = Level.parse("TRACE");
		} catch (IllegalArgumentException ignored) {
			trace = Level.FINEST;
		}
		try {
			debug = Level.parse("DEBUG");
		} catch (IllegalArgumentException ignored) {
			debug = Level.FINE;
		}
		try {
			warn = Level.parse("WARN");
		} catch (IllegalArgumentException ignored) {
			warn = Level.WARNING;
		}
		try {
			error = Level.parse("ERROR");
		} catch (IllegalArgumentException ignored) {
			error = Level.SEVERE;
		}
		try {
			info = Level.parse("INFO");
		} catch (IllegalArgumentException ignored) {
			info = Level.INFO;
		}
		TRACE = trace;
		DEBUG = debug;
		WARN = warn;
		ERROR = error;
		INFO = info;
	}

	private final Logger logger;

	/**
	 * Construct a new instance.
	 * 
	 * @param logger
	 *            the main logger to write to
	 * @param defineLogger
	 *            the main logger to write class-define-related trace messages
	 *            to
	 */
	public JDKLogger(final Logger logger) {
		this.logger = logger;
	}

	/**
	 * Construct a new instance.
	 * 
	 * @param category
	 *            the name of the logger category to write to
	 */
	public JDKLogger(final String category) {
		this(Logger.getLogger(category));
	}

	/**
	 * Construct a new instance using the category {@code org.jboss.modules}.
	 */
	public JDKLogger() {
		this("org.dding.core");
	}

	private void doLog(final Level level, final String str) {
		doLog(level, str, null);
	}

	private void doLog(final Level level, final String str, final Throwable t) {
		try {
			final ModuleLogRecord rec = new ModuleLogRecord(level, str);
			rec.setLoggerName(logger.getName());
			if (t != null)
				rec.setThrown(t);
			logger.log(rec);
		} catch (Throwable ignored) {
		}
	}

	@Override
	public void trace(Throwable t) {
		if (logger.isLoggable(TRACE)) {
			doLog(TRACE, t.getMessage(), t);
		}
	}

	public void trace(final String message) {
		if (logger.isLoggable(TRACE)) {
			doLog(TRACE, message, null);
		}
	}

	public void trace(final String format, final Object arg1) {
		if (logger.isLoggable(TRACE)) {
			doLog(TRACE, String.format(format, arg1), null);
		}
	}

	public void trace(final String format, final Object arg1, final Object arg2) {
		if (logger.isLoggable(TRACE)) {
			doLog(TRACE, String.format(format, arg1, arg2));
		}
	}

	public void trace(final String format, final Object arg1,
			final Object arg2, final Object arg3) {
		if (logger.isLoggable(TRACE)) {
			doLog(TRACE, String.format(format, arg1, arg2, arg3));
		}
	}

	public void trace(final String format, final Object... args) {
		if (logger.isLoggable(TRACE)) {
			doLog(TRACE, String.format(format, (Object[]) args));
		}
	}

	public void trace(final Throwable t, final String message) {
		doLog(TRACE, message, t);
	}

	public void trace(final Throwable t, final String format, final Object arg1) {
		if (logger.isLoggable(TRACE)) {
			doLog(TRACE, String.format(format, arg1), t);
		}
	}

	public void trace(final Throwable t, final String format,
			final Object arg1, final Object arg2) {
		if (logger.isLoggable(TRACE)) {
			doLog(TRACE, String.format(format, arg1, arg2), t);
		}
	}

	public void trace(final Throwable t, final String format,
			final Object arg1, final Object arg2, final Object arg3) {
		if (logger.isLoggable(TRACE)) {
			doLog(TRACE, String.format(format, arg1, arg2, arg3), t);
		}
	}

	public void trace(final Throwable t, final String format,
			final Object... args) {
		if (logger.isLoggable(TRACE)) {
			doLog(TRACE, String.format(format, (Object[]) args), t);
		}
	}

	@Override
	public void info(Throwable t) {
		if (logger.isLoggable(INFO)) {
			doLog(INFO, t.getMessage(), t);
		}
	}

	public void info(final String message) {
		if (logger.isLoggable(INFO)) {
			doLog(INFO, message, null);
		}
	}

	public void info(final String format, final Object arg1) {
		if (logger.isLoggable(INFO)) {
			doLog(INFO, String.format(format, arg1), null);
		}
	}

	public void info(final String format, final Object arg1, final Object arg2) {
		if (logger.isLoggable(INFO)) {
			doLog(INFO, String.format(format, arg1, arg2));
		}
	}

	public void info(final String format, final Object arg1, final Object arg2,
			final Object arg3) {
		if (logger.isLoggable(INFO)) {
			doLog(INFO, String.format(format, arg1, arg2, arg3));
		}
	}

	public void info(final String format, final Object... args) {
		if (logger.isLoggable(INFO)) {
			doLog(INFO, String.format(format, (Object[]) args));
		}
	}

	public void info(final Throwable t, final String message) {
		if (logger.isLoggable(INFO)) {
			doLog(INFO, message, t);
		}
	}

	public void info(final Throwable t, final String format, final Object arg1) {
		if (logger.isLoggable(INFO)) {
			doLog(INFO, String.format(format, arg1), t);
		}
	}

	public void info(final Throwable t, final String format, final Object arg1,
			final Object arg2) {
		if (logger.isLoggable(INFO)) {
			doLog(INFO, String.format(format, arg1, arg2), t);
		}
	}

	public void info(final Throwable t, final String format, final Object arg1,
			final Object arg2, final Object arg3) {
		if (logger.isLoggable(INFO)) {
			doLog(INFO, String.format(format, arg1, arg2, arg3), t);
		}
	}

	public void info(final Throwable t, final String format,
			final Object... args) {
		if (logger.isLoggable(INFO)) {
			doLog(INFO, String.format(format, (Object[]) args), t);
		}
	}

	@Override
	public void warn(Throwable t) {
		if (logger.isLoggable(WARN)) {
			doLog(WARN, t.getMessage(), t);
		}
	}

	public void warn(final String message) {
		if (logger.isLoggable(WARN)) {
			doLog(WARN, message, null);
		}
	}

	public void warn(final String format, final Object arg1) {
		if (logger.isLoggable(WARN)) {
			doLog(WARN, String.format(format, arg1), null);
		}
	}

	public void warn(final String format, final Object arg1, final Object arg2) {
		if (logger.isLoggable(WARN)) {
			doLog(WARN, String.format(format, arg1, arg2));
		}
	}

	public void warn(final String format, final Object arg1, final Object arg2,
			final Object arg3) {
		if (logger.isLoggable(WARN)) {
			doLog(WARN, String.format(format, arg1, arg2, arg3));
		}
	}

	public void warn(final String format, final Object... args) {
		if (logger.isLoggable(WARN)) {
			doLog(WARN, String.format(format, (Object[]) args));
		}
	}

	public void warn(final Throwable t, final String message) {
		if (logger.isLoggable(WARN)) {
			doLog(WARN, message, t);
		}
	}

	public void warn(final Throwable t, final String format, final Object arg1) {
		if (logger.isLoggable(WARN)) {
			doLog(WARN, String.format(format, arg1), t);
		}
	}

	public void warn(final Throwable t, final String format, final Object arg1,
			final Object arg2) {
		if (logger.isLoggable(WARN)) {
			doLog(WARN, String.format(format, arg1, arg2), t);
		}
	}

	public void warn(final Throwable t, final String format, final Object arg1,
			final Object arg2, final Object arg3) {
		if (logger.isLoggable(WARN)) {
			doLog(WARN, String.format(format, arg1, arg2, arg3), t);
		}
	}

	public void warn(final Throwable t, final String format,
			final Object... args) {
		if (logger.isLoggable(WARN)) {
			doLog(WARN, String.format(format, (Object[]) args), t);
		}
	}

	@Override
	public void debug(Throwable t) {
		if (logger.isLoggable(DEBUG)) {
			doLog(DEBUG, t.getMessage(), t);
		}
	}

	public void debug(final String message) {
		if (logger.isLoggable(DEBUG)) {
			doLog(DEBUG, message, null);
		}
	}

	public void debug(final String format, final Object arg1) {
		if (logger.isLoggable(DEBUG)) {
			doLog(DEBUG, String.format(format, arg1), null);
		}
	}

	public void debug(final String format, final Object arg1, final Object arg2) {
		if (logger.isLoggable(DEBUG)) {
			doLog(DEBUG, String.format(format, arg1, arg2));
		}
	}

	public void debug(final String format, final Object arg1,
			final Object arg2, final Object arg3) {
		if (logger.isLoggable(DEBUG)) {
			doLog(DEBUG, String.format(format, arg1, arg2, arg3));
		}
	}

	public void debug(final String format, final Object... args) {
		if (logger.isLoggable(DEBUG)) {
			doLog(DEBUG, String.format(format, (Object[]) args));
		}
	}

	public void debug(final Throwable t, final String message) {
		if (logger.isLoggable(DEBUG)) {
			doLog(DEBUG, message, t);
		}
	}

	public void debug(final Throwable t, final String format, final Object arg1) {
		if (logger.isLoggable(DEBUG)) {
			doLog(DEBUG, String.format(format, arg1), t);
		}
	}

	public void debug(final Throwable t, final String format,
			final Object arg1, final Object arg2) {
		if (logger.isLoggable(DEBUG)) {
			doLog(DEBUG, String.format(format, arg1, arg2), t);
		}
	}

	public void debug(final Throwable t, final String format,
			final Object arg1, final Object arg2, final Object arg3) {
		if (logger.isLoggable(DEBUG)) {
			doLog(DEBUG, String.format(format, arg1, arg2, arg3), t);
		}
	}

	public void debug(final Throwable t, final String format,
			final Object... args) {
		if (logger.isLoggable(DEBUG)) {
			doLog(DEBUG, String.format(format, (Object[]) args), t);
		}
	}

	public void error(final String message) {
		if (logger.isLoggable(ERROR)) {
			doLog(ERROR, message, null);
		}
	}

	public void error(final String format, final Object arg1) {
		if (logger.isLoggable(ERROR)) {
			doLog(ERROR, String.format(format, arg1), null);
		}
	}

	public void error(final String format, final Object arg1, final Object arg2) {
		if (logger.isLoggable(ERROR)) {
			doLog(ERROR, String.format(format, arg1, arg2));
		}
	}

	public void error(final String format, final Object arg1,
			final Object arg2, final Object arg3) {
		if (logger.isLoggable(ERROR)) {
			doLog(ERROR, String.format(format, arg1, arg2, arg3));
		}
	}

	public void error(final String format, final Object... args) {
		if (logger.isLoggable(ERROR)) {
			doLog(ERROR, String.format(format, (Object[]) args));
		}
	}

	public void error(final Throwable t, final String message) {
		if (logger.isLoggable(ERROR)) {
			doLog(ERROR, message, t);
		}
	}

	public void error(final Throwable t, final String format, final Object arg1) {
		if (logger.isLoggable(ERROR)) {
			doLog(ERROR, String.format(format, arg1), t);
		}
	}

	public void error(final Throwable t, final String format,
			final Object arg1, final Object arg2) {
		if (logger.isLoggable(ERROR)) {
			doLog(ERROR, String.format(format, arg1, arg2), t);
		}
	}

	public void error(final Throwable t, final String format,
			final Object arg1, final Object arg2, final Object arg3) {
		if (logger.isLoggable(ERROR)) {
			doLog(ERROR, String.format(format, arg1, arg2, arg3), t);
		}
	}

	public void error(final Throwable t, final String format,
			final Object... args) {
		if (logger.isLoggable(ERROR)) {
			doLog(ERROR, String.format(format, (Object[]) args), t);
		}
	}

	@Override
	public void error(Throwable t) {
		if (logger.isLoggable(ERROR)) {
			doLog(ERROR, t.getMessage(), t);
		}
	}
}
